import sys
import threading
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

# 帮我们直接运行此文件时，可以加载到上级目录的ui包
# 注意，需要放在导入ui包的前面
sys.path.append("../")

from ui.Ui_ble_control_widget import Ui_BleControlWidget
from drivers.driver_bluetooth import *
from common.utils import *
from common.hex_util import *

class BleControlWidget(QWidget):
    # 信号定义
    devices_signal = pyqtSignal(list)
    recv_data_signal = pyqtSignal(bytes)
    conn_flag_signal = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        # 实例化ui模块对象，调用setupUi()方法
        self.ui = Ui_BleControlWidget()
        self.ui.setupUi(self)
        
        # 实例属性
        self.devices = [] # 设备列表
        self.bdt: BluetoothDataTransfer = None
        
        
        # 初始化UI界面
        self.init_ui()
    
    def devices_signal_slot(self, devices):
        print("设备列表自定义信号槽函数")
        self.devices = devices
        self.ui.comboBox.clear()
        for device in devices:
            self.ui.comboBox.addItem(device[1])
            
        # 展开下拉框
        self.ui.comboBox.showPopup()
        
        # 扫描完成后，连接设备按钮使能可用
        self.ui.connectBtn.setEnabled(True)

    def refresh_devices(self):
        print("刷新设备列表线程处理函数")
        print("=========================================开始扫描")
        devices = BluetoothDataTransfer.scan_devices()
        # for device in devices:
        #     print(device)
        # print(devices)
        # print([device[1] for device in devices])
        # 信号发射
        self.devices_signal.emit(devices)
        print("=========================================结束扫描")
        
    def refreshBtnSlot(self):
        print("扫描按钮槽函数")
        # 进来就把按钮禁用
        self.ui.refreshBtn.setEnabled(False)
        
        # 创建线程，设置为守护线程
        t = threading.Thread(target=self.refresh_devices, daemon=True)
        t.start()
    
    def recv_data_signal_slot(self, bytes_arr):
        print("接收数据自定义信号槽函数")
        msg = decode_data(bytes_arr)
        print(msg) 
        
        # [distance]117.13
        pos = msg.find("]")
        if pos!= -1:
            cmd = msg[1:pos]
            if cmd == "distance":
                txt = msg[pos+1:]
                txt = f"距离障碍物：{txt} cm"
            # else:
            #     txt = f"距离障碍物少于 30 cm"
                
                # 弹出警告框，内容为txt
                QMessageBox.warning(self, "警告", txt)
            
    def conn_flag_signal_slot(self):
        print("连接设备自定义信号槽函数")
        self.update_state()

    def connect_device(self, device):
        print("连接设备线程处理函数")
        addr, name = device
        self.bdt = BluetoothDataTransfer(addr, name, 1)  # 替换为目标设备的蓝牙地址和端口号
        if not self.bdt.connect():
            print("连接失败")
            # 弹出警告框
            QMessageBox.warning(self, "警告", "连接失败")
            return
        
        print("连接成功") 
        # 发送信号
        self.conn_flag_signal.emit()
        
        try:
            print("开始接收数据")
            while True:
                bytes_arr = self.bdt.receive_data()
                if bytes_arr:
                    # 信号发射
                    self.recv_data_signal.emit(bytes_arr)
                    # msg = decode_data(bytes_arr)
                    # print(msg)
                else:
                    # 当主动调用disconnect或设备被动断开时
                    # bytes_arr会收到长度为零bytes
                    break
        except Exception as e:
            print(e)

    def connectBtnSlot(self):
        print("连接按钮槽函数")
        if self.bdt is not None:
            # 断开蓝牙
            self.bdt.disconnect()
            self.bdt = None
            self.update_state()
            return
        
        
        # 读取cb_devices中选中的设备
        device_index = self.ui.comboBox.currentIndex()
        if device_index == -1:
            print("未选择任何设备，请重新选择")
            # 弹出警告框
            QMessageBox.warning(self, "警告", "未选择任何设备，请重新选择")
            return
        device = self.devices[device_index]
        print("连接设备:", device)
        
        # 启动子线程，设置为守护线程
        t = threading.Thread(target=self.connect_device, args=(device,), daemon=True)
        t.start()
        
    def controlBtnSlot(self):
        # 如果蓝牙连接对象为None，弹出警告对话框
        if self.bdt is None:
            QMessageBox.warning(self, "警告", "蓝牙未连接")
            return
        # 获取信号发出者的对象
        sender = self.sender()

        if sender is self.ui.stopBtn:
            print("停止")
            self.bdt.send_data(b"\x00")
        elif sender is self.ui.upBtn:
            print("上")
            self.bdt.send_data(b"\x01")
        elif sender is self.ui.downBtn:
            print("下")
            self.bdt.send_data(b"\x02")
        elif sender is self.ui.leftBtn:
            print("左")
            self.bdt.send_data(b"\x03")
        elif sender is self.ui.rightBtn:
            print("右")
            self.bdt.send_data(b"\x04")
        elif sender is self.ui.rotateBtn:
            print("旋转")
            self.bdt.send_data(b"\x05")
        elif sender is self.ui.buzzerOnBtn:
            print("开喇叭")
            self.bdt.send_data(b"\x10")
        elif sender is self.ui.distanceBtn:
            print("测速")
            self.bdt.send_data(b"\x11")
        elif sender is self.ui.lightOnBtn:
            print("开灯")
            self.bdt.send_data(b"\x12")
        elif sender is self.ui.lightOffBtn:
            print("关灯")
            self.bdt.send_data(b"\x13")
        elif sender is self.ui.trackOnBtn:
            print("开轨迹")
            self.bdt.send_data(b"\x20")
        elif sender is self.ui.trackOffBtn:
            print("关轨迹")
            self.bdt.send_data(b"\x21")
            
    
        
    def init_ui(self):
        self.update_state()
        
        # 按钮信号和槽绑定
        self.ui.refreshBtn.clicked.connect(self.refreshBtnSlot) # 刷新按钮
        self.ui.connectBtn.clicked.connect(self.connectBtnSlot) # 连接按钮
        # 控制按钮绑定同一个槽函数 controlBtnSlot
        self.ui.rotateBtn.clicked.connect(self.controlBtnSlot)
        self.ui.upBtn.clicked.connect(self.controlBtnSlot)
        self.ui.buzzerOnBtn.clicked.connect(self.controlBtnSlot)
        self.ui.distanceBtn.clicked.connect(self.controlBtnSlot)
        self.ui.leftBtn.clicked.connect(self.controlBtnSlot)
        self.ui.stopBtn.clicked.connect(self.controlBtnSlot)
        self.ui.rightBtn.clicked.connect(self.controlBtnSlot)
        self.ui.lightOnBtn.clicked.connect(self.controlBtnSlot)
        self.ui.downBtn.clicked.connect(self.controlBtnSlot)
        self.ui.lightOffBtn.clicked.connect(self.controlBtnSlot)
        self.ui.trackOnBtn.clicked.connect(self.controlBtnSlot)
        self.ui.trackOffBtn.clicked.connect(self.controlBtnSlot)
        
        # 自定义信号绑定
        self.devices_signal.connect(self.devices_signal_slot)
        self.recv_data_signal.connect(self.recv_data_signal_slot)
        self.conn_flag_signal.connect(self.conn_flag_signal_slot)

    def update_state(self):
        # 蓝牙没有连接时, 只有扫描按钮能点, 其它按钮禁用
        if self.bdt is None:
            self.ui.refreshBtn.setEnabled(True)
            self.ui.connectBtn.setEnabled(False)
            self.ui.connectBtn.setText("连接蓝牙")
            self.ui.connectBtn.setIcon(QIcon(":/icon/connect"))
            self.ui.frame.setEnabled(False) # 容器里所有按钮禁用
        else:
            self.ui.refreshBtn.setEnabled(False)
            self.ui.connectBtn.setEnabled(True)
            self.ui.connectBtn.setText("断开蓝牙")
            self.ui.connectBtn.setIcon(QIcon(":/icon/disc"))
            self.ui.frame.setEnabled(True)
        


        
if __name__ == "__main__":
    app = QApplication(sys.argv)

    w = BleControlWidget()
    w.show()

    sys.exit(app.exec_())
